#Run this code first to make stipple plots along x-axis of plots
#From: http://www.cl.cam.ac.uk/~sjm217/projects/graphics/fancyaxis.R

fancyaxis <- function(side, summ, at=NULL, mingap=0.5, digits=2,
                      shiftfac=0.003, gapfac=0.003) {
  # side: like axis()
  # summ: a summary object, for example returned by summary()
  # mingap: the smallest gap permitted between two tickmarks,
  #         expressed as a fraction of the default tickmark gap
  # digits: the number of digits to round minimum and maximum to
  # shiftfac: proportion of plot width used to offset the broken axis
  # gapfac: proportion of plot width used to leave for median gap
  
  # TODO:
  # Deal with case where length(axTicks)<2
  # Deal with logarithmic axis case properly, as axTicks difference
  #  is not uniform.
  
  # Get summary information
  amin <- summ[1]
  aq1 <- summ[2]
  amed <- summ[3]
  amean <- summ[4]
  aq3 <- summ[5]
  amax <- summ[6]

  # Find out the properties of the side we are doing
  parside <-
    if (side==1){
      # Does the outside of the plot have larger or smaller vales
      flip <- 1
      # Are we on the xaxis
      xaxis <- TRUE
      # Is this axis logarithmic
      islog <- par("xlog")
      # Is the other axis logarithmic
      otherlog <- par("ylog")
      # Relevant index of par("usr")
      3
    }
    else if (side==2) {
      flip <- 1
      xaxis <- FALSE
      islog <- par("ylog")
      otherlog <- par("xlog")
      1
    }
    else if (side==3) {
      flip <- -1
      xaxis <- TRUE
      islog <- par("xlog")
      otherlog <- par("ylog")
      4
    }
    else if (side==4) {
      flip <- -1
      xaxis <- FALSE
      islog <- par("ylog")
      otherlog <- par("xlog")
      2
    }
 # Calculate default positions of ticks
  if (is.null(at))
    ticks <- axTicks(side)
  else
    ticks <- at

  # Remove any ticks outside the range
  ticks <- ticks[(ticks>=amin) & (ticks<=amax)]
  
  # Calculate the minimum desired gap between ticks
  numticks <- length(ticks)
  if (islog)
    axgap <- (log10(ticks[numticks])-log10(ticks[numticks-1]))*mingap
  else
    axgap <- (ticks[numticks]-ticks[numticks-1])*mingap

  # Get new range of tickmarks
  numticks <- length(ticks)
  firsttick <- ticks[1]
  lasttick <- ticks[numticks]
  
  # If max tick will be too close to the last tick, replace it,
  #  otherwise append it
  if (islog && (log10(amax) - log10(lasttick) < axgap)) {
    ticks[numticks]<-amax
  } else if (amax - lasttick < axgap) {
    ticks[numticks]<-amax	
  } else {	
    ticks<-c(ticks,amax)
  }
  
  # Similarly for first tick
  if (islog && (abs(log10(amin)-log10(firsttick)) < axgap)) {
    ticks[1]<-amin	
  } else if (firsttick - amin < axgap) {
    ticks[1]<-amin	
  } else {	
    ticks<-c(amin, ticks)
  }

  # Format the labels. min and max should have as many
  #  trailing zeros they were rounded to, the others
  #  should have the minimum needed to represent the tick marks
  numticks <- length(ticks)

  # Min and max
  lmin <- format(round(ticks[1], digits), nsmall=digits, trim=TRUE)
  lmax <- format(round(ticks[numticks], digits), nsmall=digits, trim=TRUE)

  # The others
  middle <- format(ticks[2:(numticks-1)], trim=TRUE)

  # Combine them
  labels <- c(lmin,middle,lmax)

  # Draw the axis
  oldlend <- par(lend = "butt")
  on.exit(par(oldlend))

  # Used for overwriting the axis line to leave tickmarks
  bg <- par("bg")
  if (bg == "transparent")
    bg <- "white"

  lwd=0.7
  # Draw the axis and tickmarks
  axis(side, ticks, labels=FALSE, col="gray50", lwd=lwd)
  # Erase the axis
  overlwd=1
  axis(side, ticks, labels=FALSE, col=bg, tcl = 0, lwd=overlwd)
  # Draw the labels
  axis(side, ticks, labels=labels, tick=FALSE)

  # Axis position
  base<-par("usr")[parside]

  # Width and height in user units
  plotwidth <- diff(par("usr")[1:2])
  plotheight <- diff(par("usr")[3:4])

  # Shift for the q2 and q3 axis from the base (in inches)
  shift <- par("pin")[1]*shiftfac*flip
  # Gap for the median
  gap <- par("pin")[1]*gapfac
  
  # Shift for the mean pointer away from the axis
  meanshift <- par("cin")[1]*0.5*flip

  # Scale lengths so both axes are equal on output device
  if (!xaxis) {
    # Y axis

    # Convert inches into user units
    shift <- shift/par("pin")[1]*plotwidth
    meanshift <- meanshift/par("pin")[1]*plotwidth
    gap <- gap/par("pin")[2]*plotheight
  } else {
    # X axis

    # Convert inches into user units
    shift <- shift/par("pin")[2]*plotheight
    meanshift <- meanshift/par("pin")[2]*plotheight
    gap <- gap/par("pin")[1]*plotwidth
  }

  if (islog) {
    # Log case on this axis (affects gap)
    lmed <- log10(amed)
    gapt <- 10^(lmed + gap)
    gapb <- 10^(lmed - gap)
  } else {
    # Linear case on this axis
    gapt <- amed + gap
    gapb <- amed - gap
  }

  # Position of q2 and q3 axis segments
  offset <- base + shift

  # Which segment is the mean in?
  if((amean>aq3) || (amean<aq1)) {
    # Mean is in q1/q4, so move relative to base
    meanbase <- base - meanshift
  } else {
    # Mean is in q2/q3, so move relative to shifted base
    meanbase <- offset - meanshift
  }

  if (otherlog) {
    # Log case on the other axis (affects shift, base, meanshift)
    meanbase <- 10^meanbase
    offset <- 10^offset
    base <- 10^base
  }

  # Stops the lines overrunning
  par(lend = "butt")

  # Line width for axis lines
  lwd=1

  # Draw q1 and q4 axis segments
  if (!xaxis) {
    #     xs,         ys,          Don't clip, Line width, Don't overlap 
    lines(rep(base,2),c(amin,aq1), xpd=TRUE, lwd=lwd)
    lines(rep(base,2),c(aq3,amax), xpd=TRUE, lwd=lwd)
  } else {
    lines(c(amin,aq1),rep(base,2), xpd=TRUE, lwd=lwd)
    lines(c(aq3,amax),rep(base,2), xpd=TRUE, lwd=lwd)
  }

  # Draw q2 and q3 axis segments
  if (!xaxis) {
    lines(rep(offset,2),c(aq1,gapb), xpd=TRUE, lwd=lwd)
    lines(rep(offset,2),c(gapt,aq3), xpd=TRUE, lwd=lwd)
  } else {
    lines(c(aq1,gapb),rep(offset,2), xpd=TRUE, lwd=lwd)
    lines(c(gapt,aq3),rep(offset,2), xpd=TRUE, lwd=lwd)
  }
  

  # Draw the mean
  if (!xaxis) {
    points(meanbase, amean, pch=18, cex=0.7, col="red", xpd=TRUE)
  } else {
    points(amean, meanbase, pch=18, cex=0.7, col="red", xpd=TRUE)
  }
}


# Draw a stripchart on an axis, showing marginal frequency
# TODO: Does not handle log axes well
axisstripchart <- function(x, side, sshift=0.3) {
  # x:    the data from which the plots are to be produced.
  # side: as in axis()
  
  # Find out the properties of the side we are doing
  parside <-
    if (side==1){
      # Does the outside of the plot have larger or smaller vales
      flip <- 1
      # Are we on the yaxis
      yaxis <- FALSE
      # Relevant index of par("usr")
      3
    }
    else if (side==2) {
      flip <- 1
      yaxis <- TRUE
      1
    }
    else if (side==3) {
      flip <- -1
      yaxis <- FALSE
      4
    }
    else if (side==4) {
      flip <- -1
      yaxis <- TRUE
      2
    }

  # Axis position
  base<-par("usr")[parside]
  
  # Width and height in user units
  plotwidth <- diff(par("usr")[1:2])
  plotheight <- diff(par("usr")[3:4])
  
  # Shift for the q2 and q3 axis from the base (in inches)
  shift <- par("pin")[1]*0.003*flip
  # Gap for the median
  gap <- par("pin")[1]*0.003
  # Shift for the mean pointer away from the axis
  meanshift <- par("cin")[1]*0.5*flip
  # Shift away from the q2 and q3 axis for the stripchart
  stripshift <- par("cin")[1]*sshift*flip
  
  # Scale lengths so both axes are equal on output device
  if (yaxis) {
    shift <- shift/par("pin")[1]*plotwidth
    meanshift <- meanshift/par("pin")[1]*plotwidth
    stripshift <- stripshift/par("pin")[1]*plotwidth
    gap <- gap/par("pin")[2]*plotheight
  } else {
    shift <- shift/par("pin")[2]*plotheight
    meanshift <- meanshift/par("pin")[2]*plotheight
    stripshift <- stripshift/par("pin")[2]*plotheight
    gap <- gap/par("pin")[1]*plotwidth
  }

  # If vertical, stripchart assumes offset is a factor of character
  # width, if horizontal, character height (bug?). So correct for this
  if (yaxis)
    offset=flip*par("cin")[2]/par("cin")[1]
  else
    offset=flip

  # Don't clip the chart
  oldxpd <- par(xpd = TRUE)
  on.exit(par(oldxpd))
  
  stripchart(x, method="stack", vertical=yaxis, offset=offset, pch=15,
             cex=0.2, add=TRUE, at=base+shift+stripshift, col="black")
}


#Read in the data
data <- read.csv("Figure_2.csv")
data$state.party <- paste(data$recipient_state, data$recipient_party, sep = "-")

#Figure 2a
#FOR INDIVIDUAL DONATIONS

#Mean share of donations from individuals at the state-party level
mean.state <- tapply(data$share.ind, data$state.party, function(x) mean(x, na.rm = T))
m <- match(data$state.party, names(mean.state))
data$state.mean <- mean.state[m]

#De-mean the data
data$diff.mean <- data$share.ind - data$state.mean

#Loess Curve
data <- data[order(data$np_score),]
plx <- predict(loess(diff.mean ~ np_score, data = data), se = T)

#Figure 2a
plot(data$np_score, data$diff.mean, cex = 0, ylim = c(-.05, .1), xlim = c(-2.5, 2.5), ylab = "Share Individual Contributions (residualized)", xlab = "Ideology Score", main = "Ideology and Individual Contributions", axes = F, cex.main = 2, cex.lab = 1.25)
polygon(x = c(data$np_score, rev(data$np_score)), c(plx$fit + 1.96*plx$s, rev(plx$fit - 1.96*plx$s)), col = "grey", lty = 0)
lines(data$np_score, plx$fit)
axisstripchart(data$np_score[abs(data$np_score) < 2.4], side = 1)
axis(1, at = seq(-2, 2, .5))
axis(2, at = seq(-.05, .1, .02))
box()

#Figure 2b
#FOR PACS DONATIONS

#Mean share of donations from PACs at the state-party level
mean.state <- tapply(data$share.group, data$state.party, function(x) mean(x, na.rm = T))
m <- match(data$state.party, names(mean.state))

data$state.mean <- mean.state[m]
data$diff.mean <- data$share.group - data$state.mean

data <- data[order(data$np_score),]
plx <- predict(loess(diff.mean ~ np_score, data = data), se = T)

plot(data$np_score, data$diff.mean, cex = 0, ylim = c(-.05, .1), xlim = c(-2.5, 2.5), ylab = "Share PAC Contributions (residualized)", xlab = "Ideology Score", main = "Ideology and PAC Contributions", axes = F, cex.main = 2, cex.lab = 1.25)
polygon(x = c(data$np_score, rev(data$np_score)), c(plx$fit + 1.96*plx$s, rev(plx$fit - 1.96*plx$s)), col = "grey", lty = 0)
lines(data$np_score, plx$fit)
axisstripchart(data$np_score[abs(data$np_score) < 2.4], side = 1)
axis(1, at = seq(-2, 2, .5))
axis(2, at = seq(-.05, .1, .02))
box()


# Figure A5
# Total Money Raised

data$log.total <- log(data$total.raised)

data <- data[!is.na(data$np_score),]
data <- data[!is.na(data$log.total),]
data <- data[order(data$np_score),]
plx <- predict(loess(log.total ~ np_score, data = data), se = T)


par(mar = c(5, 5, 5, 2))
plot(data$np_score, data$log.total, cex = 0, xlim = c(-2.5, 2.5), ylab = "Log Total Money Raised", xlab = "Ideology Score", main = "Ideology and Total Receipts \n State Legislators", axes = F, cex.main = 2, cex.lab = 1.55)
polygon(x = c(data$np_score, rev(data$np_score)), c(plx$fit+2*plx$s, rev(plx$fit-2*plx$s)), col = "grey", lty = 0)
lines(data$np_score, plx$fit)
axisstripchart(data$np_score[abs(data$np_score) < 2.4], side = 1)
axis(1, at = seq(-2, 2, .5))
axis(2, at = seq(0, 15, 2), las = 2)
box()
